/************************************************************************/
/* Procfile is a temporary usermode interface to the process management */
/* subsystem in process.c, it allows for reading the current process    */
/* table in humanly readable format                                     */
/************************************************************************/

#include "dri.h"
#include "kmm.h"
#include <string.h>
#include <_stdlib.h>
#include "kstdio.h"
#include "dbgio.h"
#include "fcntl.h"
#include "process.h"

dri_driver_descriptor_t *procfile_dri_desc;
char *procfile_buffer = (char *) 0;
int procfile_mutex = 0;

void procfile_update(){
	procfile_mutex++;
	if (procfile_buffer != 0)
		kfree((void *)procfile_buffer);
	procfile_buffer = (char *) kmalloc(80*llist_size(process_table));
	*procfile_buffer = (char) 0x0;
	char *strb = (char *) kmalloc(100);
	LLIST *current_ll = process_table->next;
	if (current_ll == process_table)
		goto notfound;
	for (uint32_t current = 0;1;current++){
		if (current_ll->value == 0)
			continue;
		process_info_t *process = (process_info_t*) current_ll->value;
		sprintf(strb,"[%i] %s RUNNING\n",process->pid,process->name);
		//dprintf("%s",strb);
		strcat(procfile_buffer,strb);
		if (current_ll->next == process_table)
			break;
		current_ll = current_ll->next;
	}
notfound:
	kfree((void *)strb);
	strb = (char *) kmalloc(strlen(procfile_buffer));
	strcpy(strb,procfile_buffer);
	kfree((void *)procfile_buffer);
	procfile_buffer = strb;
	procfile_mutex--;
}

uint32_t procfile_read(struct vfs_node *node ,uint8_t *buffer ,uint32_t offset ,uint32_t length,uint32_t fflags){
	if (offset == 0 && procfile_mutex == 0)
		procfile_update();
	uint32_t totalLength = strlen(procfile_buffer);
	int readLength = length;
	//dprintf("Procfile read: %i | %i\n",totalLength,readLength);
	if (offset >= totalLength)
		return 0;
	if ((offset+length) > totalLength)
		length = totalLength - offset;
	memcpy((void*)buffer,(void*)(((uint32_t)procfile_buffer) + offset),readLength);
	return readLength;
}

uint32_t procfile_write(struct vfs_node *node ,uint8_t *buffer ,uint32_t offset ,uint32_t length,uint32_t fflags){
	return 0;
}

void procfile_main(){
	procfile_dri_desc = (dri_driver_descriptor_t *) kmalloc(sizeof(dri_driver_descriptor_t));
	/* Set up DRI descriptor */
	strcpy(procfile_dri_desc->driver_name,"Process Info File driver");
	procfile_dri_desc->driver_magic = DRI_DRIVER_MAGIC;
	procfile_dri_desc->driver_class = DRI_CLASS_CHAR;
	procfile_dri_desc->driver_id    = 1;
	procfile_dri_desc->driver_class_desc = (void *) 0;
	procfile_dri_desc->init_sci = dri_syscall_initialize;
	procfile_dri_desc->driver_main = dri_driver_main_stub;
	/* Register driver with DRI */
	dri_register_driver(procfile_dri_desc);
	/* Register devfs handles */
	dri_register_specfile("procfile",VFS_CHARDEVICE_FLAG,0,0x1B6,procfile_read,procfile_write);
}
